/*
 * bt_express.c
 *
 *  Created on: 2012-1-3
 *      Author: lina
 */

#include <string.h>

#include "bt_express.h"

#ifdef _tag_
#undef _tag_
#endif
#define _tag_

#if 0
bt_node_t * express2bt(const char * express)
{
	if (!express) {
		return 0;
	}

	bt_node_t * tree = 0;
	bt_node_t * node = 0;

	(void)tree;
	(void)node;

	return tree;
}

char * bt2express(bt_node_t * bt, char * buff, size_t buff_len)
{
	memset(buff, 0, buff_len);
	if (!bt) {
		return buff;
	}

	char * p = buff;
	bt_node_t * nodes[NODE_STACK_LEN + 2];
	bt_node_t * node = nodes[0];

	int cursor = 1;

	nodes[cursor] = bt;
	while (cursor) {
		node = nodes[cursor];

		*p++ = SIGN_BEGIN;
		*p++ = node->value;
		*p++ = SIGN_SEP;
		if (node->r_child) {
			nodes[cursor++] = node->r_child;
		}
		if (node->l_child) {
			nodes[cursor++] = node->l_child;
		}
	}

	return buff;
}
#endif
#if 1
int express2bt_r(const char ** express, bt_node_t ** bt)
{
#define JUMP_BLANK \
	for (; *p == SIGN_BLANK && p < end; ++p) {} \
	if (p == end) { return ERR_COMMON; } _tag_

	int ret = SUCCESS;

	const char * p = *express;
	const char * end = p + strlen(p);

	JUMP_BLANK

	if (*p++ != SIGN_BEGIN) {
		return ERR_EXPRESS;
	}

	JUMP_BLANK

	switch (*p)
	{
	case SIGN_END:
		*express = ++p;
		return ret;

	case SIGN_BEGIN:
	case SIGN_SEP:
		return ERR_EXPRESS;

	default:
		*bt = bt_node_create();
		(*bt)->value = *p++;
		break;
	}

	JUMP_BLANK

	if (*p++ != SIGN_SEP) {
		return ERR_EXPRESS;
	}

	if ((ret = express2bt_r(&p, &((*bt)->l_child)))) {
		return ret;
	}

	JUMP_BLANK

	if (*p++ != SIGN_SEP) {
		return ERR_EXPRESS;
	}

	if ((ret = express2bt_r(&p, &((*bt)->r_child)))) {
		return ret;
	}

	JUMP_BLANK

	if (*p == SIGN_SEP) {
		++p;
		JUMP_BLANK;
	}

	if (*p != SIGN_END) {
		return ERR_EXPRESS;
	}

	*express = ++p;

	return ret;
}

int bt2express_r(bt_node_t * bt, char * buff, size_t * buff_len)
{
#define LEAF_LEN 9

	if (*buff_len < LEAF_LEN) {
		return ERR_NO_MEM;
	}

	int ret = SUCCESS;

	char * p = buff;
	char * end = buff + *buff_len;
	if (bt) {
		*p++ = SIGN_BEGIN;
		*p++ = bt->value;
		*p++ = SIGN_SEP;

		size_t l_len = end - p;
		if (bt->l_child) {
			if ((ret = bt2express_r(bt->l_child, p, &l_len))) {
				return ret;
			}
			p += l_len;
		}
		else {
			*p++ = SIGN_BEGIN;
			*p++ = SIGN_END;
			l_len = 2;
		}

		if (end - p < 4) {
			return ERR_NO_MEM;
		}

		*p++ = SIGN_SEP;

		size_t r_len = end - p;
		if (bt->r_child) {
			if ((ret = bt2express_r(bt->r_child, p, &r_len))) {
				return ret;
			}
			p += r_len;
		}
		else {
			*p++ = SIGN_BEGIN;
			*p++ = SIGN_END;
			r_len = 2;
		}

		if (end - p < 1) {
			return ERR_NO_MEM;
		}

		*p++ = SIGN_END;
	}

	*buff_len = p - buff;

	return ret;
}
#endif
